﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Xml.Linq;
using AzukiMap.MapSource;
using AzukiMap.Map;

namespace AzukiMap.Layer
{
    public class LayerGroup : MapLayer
    {
        private readonly ObservableCollection<ILayer> _layers;

        private StackPanel _copyrightImage;
        private StackPanel _copyright;

        protected internal override FrameworkElement CopyrightImage
        {
            get
            {
                return _copyrightImage;
            }
            protected set
            {
                _copyrightImage = (StackPanel) value;
            }
        }

        protected internal override FrameworkElement Copyright
        {
            get
            {
                return _copyright;
            }
            protected set
            {
                _copyright = (StackPanel)value;
            }
        }

        public LayerGroup()
        {
            _layers = new ObservableCollection<ILayer>();
            _copyright = new StackPanel {Orientation = Orientation.Horizontal};
            _copyrightImage = new StackPanel {Orientation = Orientation.Horizontal};
            MapSource = new MapSourceEmpty();
        }

        public override MapCoordinate MapCoord
        {
            get { return base.MapCoord; }
            protected internal set
            {
                base.MapCoord = value;
                SetCoordTransformation();
                TransformMaxExtent();
                SetChildrenMapCoord();
            }
        }

        ~LayerGroup()
        {

        }

        public override void SetCoordTransformation()
        {
            foreach (MapLayer layer in _layers)
            {
                layer.SetCoordTransformation();
            }
        }


        public ObservableCollection<ILayer> Layers
        {
            get { return _layers; }
        }

        public void AddLayer(MapLayer layer)
        {
            AddLayerTop(layer);
        }

        public void AddLayerTop(MapLayer layer)
        {
            AddLayer(layer, 0);
        }

        public void AddLayerBottom(MapLayer layer)
        {
            AddLayer(layer, _layers.Count);
        }

        public void AddLayer(MapLayer layer, int position)
        {
            layer.MapCoord = MapCoord;
            if (position < 0)
            {
                position = 0;
            }
            if (position >= _layers.Count)
            {
                _layers.Add(layer);
                Children.Add(layer);
            }
            else
            {
                _layers.Insert(position, layer);
                Children.Insert(position, layer);
            }

            layer.LabelLayer = LabelLayer;

            if (layer.CopyrightImage != null)
            {
                if (! _copyrightImage.Children.Contains(layer.CopyrightImage))
                {
                    _copyrightImage.Children.Add(layer.CopyrightImage);
                }
            }

            if ( layer.Copyright != null )
            {
                if ( !_copyright.Children.Contains(layer.Copyright))
                {
                    _copyright.Children.Add(layer.Copyright);
                }
            }

        }

        public void RemoveLayer(MapLayer layer)
        {
            Children.Remove(layer);
            _layers.Remove(layer);
        }

        public override void Draw()
        {
            if (IsVisible)
            {
                foreach (MapLayer layer in _layers)
                {
                    layer.MoveEastWestCanvases();
                    layer.Draw();
                }
            }
        }

        public override void Clear()
        {
            foreach (MapLayer layer in _layers)
            {
                layer.Clear();
            }
        }

        public override void Redraw()
        {
            if (IsVisible)
            {
                foreach (MapLayer layer in _layers)
                {
                    layer.Redraw();
                }
            }
        }

        void SetChildrenMapCoord()
        {
            foreach (MapLayer layer in _layers)
            {
                layer.MapCoord = base.MapCoord;
                layer.SetCoordTransformation();
            }
        }

        public override void MapScaleChanged(object sender, MapScaleChangedArgs e)
        {
            base.MapScaleChanged(sender, e);
            foreach (ILayer layer in Layers)
            {
                layer.MapScaleChanged(sender, e);
            }
        }

        public override XElement ToXml()
        {
            return ToXml("LayerGroup");
        }

        public override XElement ToXml(string elementName)
        {
            var layerXml = new XElement(elementName,
                                        _xmlCommon.CreateAttr("Name", LayerName),
                                        _xmlCommon.CreateAttr("Type", Type),
                                        _xmlCommon.CreateAttr("Readable", Readable),
                                        _xmlCommon.CreateAttr("Writable", Writable),
                                        _xmlCommon.GeometryToXml("MaxExtent", MaxExtent),
                                        _xmlCommon.CreateAttr("MaxScale", MaxScale),
                                        _xmlCommon.CreateAttr("MinScale", MinScale),
                                        _xmlCommon.CreateAttr("Opacity", Opacity),
                                        _xmlCommon.CreateAttr("Visible", IsVisible),
                                        LayersToXml()
                );
            return layerXml;
        }

        IEnumerable<XElement> LayersToXml()
        {
            foreach (var layer in Layers)
            {
                yield return layer.ToXml();
            }
        }

        public override void Parse(XElement xmlSource)
        {
            var parser = new LayerXmlParser();
            foreach (XElement element in xmlSource.Elements())
            {
                MapLayer layer = parser.Parse(element);
                if ( layer != null )
                    AddLayer(layer);
            }
        }
    }
}